home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / httplib.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  30KB  |  1,209 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. import errno
  5. import mimetools
  6. import socket
  7. from urlparse import urlsplit
  8.  
  9. try:
  10.     from cStringIO import StringIO
  11. except ImportError:
  12.     from StringIO import StringIO
  13.  
  14. __all__ = [
  15.     'HTTP',
  16.     'HTTPResponse',
  17.     'HTTPConnection',
  18.     'HTTPSConnection',
  19.     'HTTPException',
  20.     'NotConnected',
  21.     'UnknownProtocol',
  22.     'UnknownTransferEncoding',
  23.     'UnimplementedFileMode',
  24.     'IncompleteRead',
  25.     'InvalidURL',
  26.     'ImproperConnectionState',
  27.     'CannotSendRequest',
  28.     'CannotSendHeader',
  29.     'ResponseNotReady',
  30.     'BadStatusLine',
  31.     'error',
  32.     'responses']
  33. HTTP_PORT = 80
  34. HTTPS_PORT = 443
  35. _UNKNOWN = 'UNKNOWN'
  36. _CS_IDLE = 'Idle'
  37. _CS_REQ_STARTED = 'Request-started'
  38. _CS_REQ_SENT = 'Request-sent'
  39. CONTINUE = 100
  40. SWITCHING_PROTOCOLS = 101
  41. PROCESSING = 102
  42. OK = 200
  43. CREATED = 201
  44. ACCEPTED = 202
  45. NON_AUTHORITATIVE_INFORMATION = 203
  46. NO_CONTENT = 204
  47. RESET_CONTENT = 205
  48. PARTIAL_CONTENT = 206
  49. MULTI_STATUS = 207
  50. IM_USED = 226
  51. MULTIPLE_CHOICES = 300
  52. MOVED_PERMANENTLY = 301
  53. FOUND = 302
  54. SEE_OTHER = 303
  55. NOT_MODIFIED = 304
  56. USE_PROXY = 305
  57. TEMPORARY_REDIRECT = 307
  58. BAD_REQUEST = 400
  59. UNAUTHORIZED = 401
  60. PAYMENT_REQUIRED = 402
  61. FORBIDDEN = 403
  62. NOT_FOUND = 404
  63. METHOD_NOT_ALLOWED = 405
  64. NOT_ACCEPTABLE = 406
  65. PROXY_AUTHENTICATION_REQUIRED = 407
  66. REQUEST_TIMEOUT = 408
  67. CONFLICT = 409
  68. GONE = 410
  69. LENGTH_REQUIRED = 411
  70. PRECONDITION_FAILED = 412
  71. REQUEST_ENTITY_TOO_LARGE = 413
  72. REQUEST_URI_TOO_LONG = 414
  73. UNSUPPORTED_MEDIA_TYPE = 415
  74. REQUESTED_RANGE_NOT_SATISFIABLE = 416
  75. EXPECTATION_FAILED = 417
  76. UNPROCESSABLE_ENTITY = 422
  77. LOCKED = 423
  78. FAILED_DEPENDENCY = 424
  79. UPGRADE_REQUIRED = 426
  80. INTERNAL_SERVER_ERROR = 500
  81. NOT_IMPLEMENTED = 501
  82. BAD_GATEWAY = 502
  83. SERVICE_UNAVAILABLE = 503
  84. GATEWAY_TIMEOUT = 504
  85. HTTP_VERSION_NOT_SUPPORTED = 505
  86. INSUFFICIENT_STORAGE = 507
  87. NOT_EXTENDED = 510
  88. responses = {
  89.     100: 'Continue',
  90.     101: 'Switching Protocols',
  91.     200: 'OK',
  92.     201: 'Created',
  93.     202: 'Accepted',
  94.     203: 'Non-Authoritative Information',
  95.     204: 'No Content',
  96.     205: 'Reset Content',
  97.     206: 'Partial Content',
  98.     300: 'Multiple Choices',
  99.     301: 'Moved Permanently',
  100.     302: 'Found',
  101.     303: 'See Other',
  102.     304: 'Not Modified',
  103.     305: 'Use Proxy',
  104.     306: '(Unused)',
  105.     307: 'Temporary Redirect',
  106.     400: 'Bad Request',
  107.     401: 'Unauthorized',
  108.     402: 'Payment Required',
  109.     403: 'Forbidden',
  110.     404: 'Not Found',
  111.     405: 'Method Not Allowed',
  112.     406: 'Not Acceptable',
  113.     407: 'Proxy Authentication Required',
  114.     408: 'Request Timeout',
  115.     409: 'Conflict',
  116.     410: 'Gone',
  117.     411: 'Length Required',
  118.     412: 'Precondition Failed',
  119.     413: 'Request Entity Too Large',
  120.     414: 'Request-URI Too Long',
  121.     415: 'Unsupported Media Type',
  122.     416: 'Requested Range Not Satisfiable',
  123.     417: 'Expectation Failed',
  124.     500: 'Internal Server Error',
  125.     501: 'Not Implemented',
  126.     502: 'Bad Gateway',
  127.     503: 'Service Unavailable',
  128.     504: 'Gateway Timeout',
  129.     505: 'HTTP Version Not Supported' }
  130. MAXAMOUNT = 1048576
  131.  
  132. class HTTPMessage(mimetools.Message):
  133.     
  134.     def addheader(self, key, value):
  135.         prev = self.dict.get(key)
  136.         if prev is None:
  137.             self.dict[key] = value
  138.         else:
  139.             combined = ', '.join((prev, value))
  140.             self.dict[key] = combined
  141.  
  142.     
  143.     def addcontinue(self, key, more):
  144.         prev = self.dict[key]
  145.         self.dict[key] = prev + '\n ' + more
  146.  
  147.     
  148.     def readheaders(self):
  149.         self.dict = { }
  150.         self.unixfrom = ''
  151.         self.headers = hlist = []
  152.         self.status = ''
  153.         headerseen = ''
  154.         firstline = 1
  155.         startofline = None
  156.         unread = None
  157.         tell = None
  158.         if hasattr(self.fp, 'unread'):
  159.             unread = self.fp.unread
  160.         elif self.seekable:
  161.             tell = self.fp.tell
  162.         
  163.         while True:
  164.             if tell:
  165.                 
  166.                 try:
  167.                     startofline = tell()
  168.                 except IOError:
  169.                     startofline = None
  170.                     tell = None
  171.                     self.seekable = 0
  172.                 except:
  173.                     None<EXCEPTION MATCH>IOError
  174.                 
  175.  
  176.             None<EXCEPTION MATCH>IOError
  177.             line = self.fp.readline()
  178.             if not line:
  179.                 self.status = 'EOF in headers'
  180.                 break
  181.             
  182.             if firstline and line.startswith('From '):
  183.                 self.unixfrom = self.unixfrom + line
  184.                 continue
  185.             
  186.             firstline = 0
  187.             if headerseen and line[0] in ' \t':
  188.                 hlist.append(line)
  189.                 self.addcontinue(headerseen, line.strip())
  190.                 continue
  191.             elif self.iscomment(line):
  192.                 continue
  193.             elif self.islast(line):
  194.                 break
  195.             
  196.             headerseen = self.isheader(line)
  197.             if headerseen:
  198.                 hlist.append(line)
  199.                 self.addheader(headerseen, line[len(headerseen) + 1:].strip())
  200.                 continue
  201.                 continue
  202.             if not self.dict:
  203.                 self.status = 'No headers'
  204.             else:
  205.                 self.status = 'Non-header line where header expected'
  206.             if unread:
  207.                 unread(line)
  208.             elif tell:
  209.                 self.fp.seek(startofline)
  210.             else:
  211.                 self.status = self.status + '; bad seek'
  212.             break
  213.  
  214.  
  215.  
  216. class HTTPResponse:
  217.     
  218.     def __init__(self, sock, debuglevel = 0, strict = 0, method = None):
  219.         self.fp = sock.makefile('rb', 0)
  220.         self.debuglevel = debuglevel
  221.         self.strict = strict
  222.         self._method = method
  223.         self.msg = None
  224.         self.version = _UNKNOWN
  225.         self.status = _UNKNOWN
  226.         self.reason = _UNKNOWN
  227.         self.chunked = _UNKNOWN
  228.         self.chunk_left = _UNKNOWN
  229.         self.length = _UNKNOWN
  230.         self.will_close = _UNKNOWN
  231.  
  232.     
  233.     def _read_status(self):
  234.         line = self.fp.readline()
  235.         if self.debuglevel > 0:
  236.             print 'reply:', repr(line)
  237.         
  238.         if not line:
  239.             raise BadStatusLine(line)
  240.         
  241.         
  242.         try:
  243.             (version, status, reason) = line.split(None, 2)
  244.         except ValueError:
  245.             
  246.             try:
  247.                 (version, status) = line.split(None, 1)
  248.                 reason = ''
  249.             except ValueError:
  250.                 version = ''
  251.             except:
  252.                 None<EXCEPTION MATCH>ValueError
  253.             
  254.  
  255.             None<EXCEPTION MATCH>ValueError
  256.  
  257.         if not version.startswith('HTTP/'):
  258.             if self.strict:
  259.                 self.close()
  260.                 raise BadStatusLine(line)
  261.             else:
  262.                 self.fp = LineAndFileWrapper(line, self.fp)
  263.                 return ('HTTP/0.9', 200, '')
  264.         
  265.         
  266.         try:
  267.             status = int(status)
  268.             if status < 100 or status > 999:
  269.                 raise BadStatusLine(line)
  270.         except ValueError:
  271.             raise BadStatusLine(line)
  272.  
  273.         return (version, status, reason)
  274.  
  275.     
  276.     def begin(self):
  277.         if self.msg is not None:
  278.             return None
  279.         
  280.         while True:
  281.             (version, status, reason) = self._read_status()
  282.             if status != CONTINUE:
  283.                 break
  284.             
  285.             while True:
  286.                 skip = self.fp.readline().strip()
  287.                 if not skip:
  288.                     break
  289.                 
  290.                 if self.debuglevel > 0:
  291.                     print 'header:', skip
  292.                     continue
  293.         self.status = status
  294.         self.reason = reason.strip()
  295.         if version == 'HTTP/1.0':
  296.             self.version = 10
  297.         elif version.startswith('HTTP/1.'):
  298.             self.version = 11
  299.         elif version == 'HTTP/0.9':
  300.             self.version = 9
  301.         else:
  302.             raise UnknownProtocol(version)
  303.         if self.version == 9:
  304.             self.length = None
  305.             self.chunked = 0
  306.             self.will_close = 1
  307.             self.msg = HTTPMessage(StringIO())
  308.             return None
  309.         
  310.         self.msg = HTTPMessage(self.fp, 0)
  311.         if self.debuglevel > 0:
  312.             for hdr in self.msg.headers:
  313.                 print 'header:', hdr,
  314.             
  315.         
  316.         self.msg.fp = None
  317.         tr_enc = self.msg.getheader('transfer-encoding')
  318.         if tr_enc and tr_enc.lower() == 'chunked':
  319.             self.chunked = 1
  320.             self.chunk_left = None
  321.         else:
  322.             self.chunked = 0
  323.         self.will_close = self._check_close()
  324.         length = self.msg.getheader('content-length')
  325.         if length and not (self.chunked):
  326.             
  327.             try:
  328.                 self.length = int(length)
  329.             except ValueError:
  330.                 self.length = None
  331.             except:
  332.                 None<EXCEPTION MATCH>ValueError
  333.             
  334.  
  335.         None<EXCEPTION MATCH>ValueError
  336.         self.length = None
  337.         if not status == NO_CONTENT and status == NOT_MODIFIED:
  338.             if status <= status:
  339.                 pass
  340.             elif status < 200 or self._method == 'HEAD':
  341.                 self.length = 0
  342.             
  343.         if not (self.will_close) and not (self.chunked) and self.length is None:
  344.             self.will_close = 1
  345.         
  346.  
  347.     
  348.     def _check_close(self):
  349.         conn = self.msg.getheader('connection')
  350.         if self.version == 11:
  351.             conn = self.msg.getheader('connection')
  352.             if conn and 'close' in conn.lower():
  353.                 return True
  354.             
  355.             return False
  356.         
  357.         if self.msg.getheader('keep-alive'):
  358.             return False
  359.         
  360.         if conn and 'keep-alive' in conn.lower():
  361.             return False
  362.         
  363.         pconn = self.msg.getheader('proxy-connection')
  364.         if pconn and 'keep-alive' in pconn.lower():
  365.             return False
  366.         
  367.         return True
  368.  
  369.     
  370.     def close(self):
  371.         if self.fp:
  372.             self.fp.close()
  373.             self.fp = None
  374.         
  375.  
  376.     
  377.     def isclosed(self):
  378.         return self.fp is None
  379.  
  380.     
  381.     def read(self, amt = None):
  382.         if self.fp is None:
  383.             return ''
  384.         
  385.         if self.chunked:
  386.             return self._read_chunked(amt)
  387.         
  388.         if amt is None:
  389.             if self.length is None:
  390.                 s = self.fp.read()
  391.             else:
  392.                 s = self._safe_read(self.length)
  393.                 self.length = 0
  394.             self.close()
  395.             return s
  396.         
  397.         if self.length is not None:
  398.             if amt > self.length:
  399.                 amt = self.length
  400.             
  401.         
  402.         s = self.fp.read(amt)
  403.         if self.length is not None:
  404.             self.length -= len(s)
  405.         
  406.         return s
  407.  
  408.     
  409.     def _read_chunked(self, amt):
  410.         chunk_left = self.chunk_left
  411.         value = ''
  412.         while True:
  413.             if chunk_left is None:
  414.                 line = self.fp.readline()
  415.                 i = line.find(';')
  416.                 if i >= 0:
  417.                     line = line[:i]
  418.                 
  419.                 chunk_left = int(line, 16)
  420.                 if chunk_left == 0:
  421.                     break
  422.                 
  423.             
  424.             if amt is None:
  425.                 value += self._safe_read(chunk_left)
  426.             elif amt < chunk_left:
  427.                 value += self._safe_read(amt)
  428.                 self.chunk_left = chunk_left - amt
  429.                 return value
  430.             elif amt == chunk_left:
  431.                 value += self._safe_read(amt)
  432.                 self._safe_read(2)
  433.                 self.chunk_left = None
  434.                 return value
  435.             else:
  436.                 value += self._safe_read(chunk_left)
  437.                 amt -= chunk_left
  438.             self._safe_read(2)
  439.             chunk_left = None
  440.         while True:
  441.             line = self.fp.readline()
  442.             if not line:
  443.                 break
  444.             
  445.             if line == '\r\n':
  446.                 break
  447.                 continue
  448.         self.close()
  449.         return value
  450.  
  451.     
  452.     def _safe_read(self, amt):
  453.         s = []
  454.         while amt > 0:
  455.             chunk = self.fp.read(min(amt, MAXAMOUNT))
  456.             if not chunk:
  457.                 raise IncompleteRead(s)
  458.             
  459.             s.append(chunk)
  460.             amt -= len(chunk)
  461.         return ''.join(s)
  462.  
  463.     
  464.     def getheader(self, name, default = None):
  465.         if self.msg is None:
  466.             raise ResponseNotReady()
  467.         
  468.         return self.msg.getheader(name, default)
  469.  
  470.     
  471.     def getheaders(self):
  472.         if self.msg is None:
  473.             raise ResponseNotReady()
  474.         
  475.         return self.msg.items()
  476.  
  477.  
  478.  
  479. class HTTPConnection:
  480.     _http_vsn = 11
  481.     _http_vsn_str = 'HTTP/1.1'
  482.     response_class = HTTPResponse
  483.     default_port = HTTP_PORT
  484.     auto_open = 1
  485.     debuglevel = 0
  486.     strict = 0
  487.     
  488.     def __init__(self, host, port = None, strict = None):
  489.         self.sock = None
  490.         self._buffer = []
  491.         self._HTTPConnection__response = None
  492.         self._HTTPConnection__state = _CS_IDLE
  493.         self._method = None
  494.         self._set_hostport(host, port)
  495.         if strict is not None:
  496.             self.strict = strict
  497.         
  498.  
  499.     
  500.     def _set_hostport(self, host, port):
  501.         if port is None:
  502.             i = host.rfind(':')
  503.             j = host.rfind(']')
  504.             if i > j:
  505.                 
  506.                 try:
  507.                     port = int(host[i + 1:])
  508.                 except ValueError:
  509.                     raise InvalidURL("nonnumeric port: '%s'" % host[i + 1:])
  510.  
  511.                 host = host[:i]
  512.             else:
  513.                 port = self.default_port
  514.             if host and host[0] == '[' and host[-1] == ']':
  515.                 host = host[1:-1]
  516.             
  517.         
  518.         self.host = host
  519.         self.port = port
  520.  
  521.     
  522.     def set_debuglevel(self, level):
  523.         self.debuglevel = level
  524.  
  525.     
  526.     def connect(self):
  527.         msg = 'getaddrinfo returns an empty list'
  528.         for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
  529.             (af, socktype, proto, canonname, sa) = res
  530.             
  531.             try:
  532.                 self.sock = socket.socket(af, socktype, proto)
  533.                 if self.debuglevel > 0:
  534.                     print 'connect: (%s, %s)' % (self.host, self.port)
  535.                 
  536.                 self.sock.connect(sa)
  537.             except socket.error:
  538.                 msg = None
  539.                 if self.debuglevel > 0:
  540.                     print 'connect fail:', (self.host, self.port)
  541.                 
  542.                 if self.sock:
  543.                     self.sock.close()
  544.                 
  545.                 self.sock = None
  546.                 continue
  547.  
  548.             break
  549.         
  550.         if not self.sock:
  551.             raise socket.error, msg
  552.         
  553.  
  554.     
  555.     def close(self):
  556.         if self.sock:
  557.             self.sock.close()
  558.             self.sock = None
  559.         
  560.         if self._HTTPConnection__response:
  561.             self._HTTPConnection__response.close()
  562.             self._HTTPConnection__response = None
  563.         
  564.         self._HTTPConnection__state = _CS_IDLE
  565.  
  566.     
  567.     def send(self, str):
  568.         if self.sock is None:
  569.             if self.auto_open:
  570.                 self.connect()
  571.             else:
  572.                 raise NotConnected()
  573.         
  574.         if self.debuglevel > 0:
  575.             print 'send:', repr(str)
  576.         
  577.         
  578.         try:
  579.             self.sock.sendall(str)
  580.         except socket.error:
  581.             v = None
  582.             if v[0] == 32:
  583.                 self.close()
  584.             
  585.             raise 
  586.  
  587.  
  588.     
  589.     def _output(self, s):
  590.         self._buffer.append(s)
  591.  
  592.     
  593.     def _send_output(self):
  594.         self._buffer.extend(('', ''))
  595.         msg = '\r\n'.join(self._buffer)
  596.         del self._buffer[:]
  597.         self.send(msg)
  598.  
  599.     
  600.     def putrequest(self, method, url, skip_host = 0, skip_accept_encoding = 0):
  601.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  602.             self._HTTPConnection__response = None
  603.         
  604.         if self._HTTPConnection__state == _CS_IDLE:
  605.             self._HTTPConnection__state = _CS_REQ_STARTED
  606.         else:
  607.             raise CannotSendRequest()
  608.         self._method = method
  609.         if not url:
  610.             url = '/'
  611.         
  612.         str = '%s %s %s' % (method, url, self._http_vsn_str)
  613.         self._output(str)
  614.         if self._http_vsn == 11:
  615.             if not skip_host:
  616.                 netloc = ''
  617.                 if url.startswith('http'):
  618.                     (nil, netloc, nil, nil, nil) = urlsplit(url)
  619.                 
  620.                 if netloc:
  621.                     
  622.                     try:
  623.                         netloc_enc = netloc.encode('ascii')
  624.                     except UnicodeEncodeError:
  625.                         netloc_enc = netloc.encode('idna')
  626.  
  627.                     self.putheader('Host', netloc_enc)
  628.                 else:
  629.                     
  630.                     try:
  631.                         host_enc = self.host.encode('ascii')
  632.                     except UnicodeEncodeError:
  633.                         host_enc = self.host.encode('idna')
  634.  
  635.                     if self.port == HTTP_PORT:
  636.                         self.putheader('Host', host_enc)
  637.                     else:
  638.                         self.putheader('Host', '%s:%s' % (host_enc, self.port))
  639.             
  640.             if not skip_accept_encoding:
  641.                 self.putheader('Accept-Encoding', 'identity')
  642.             
  643.         
  644.  
  645.     
  646.     def putheader(self, header, value):
  647.         if self._HTTPConnection__state != _CS_REQ_STARTED:
  648.             raise CannotSendHeader()
  649.         
  650.         str = '%s: %s' % (header, value)
  651.         self._output(str)
  652.  
  653.     
  654.     def endheaders(self):
  655.         if self._HTTPConnection__state == _CS_REQ_STARTED:
  656.             self._HTTPConnection__state = _CS_REQ_SENT
  657.         else:
  658.             raise CannotSendHeader()
  659.         self._send_output()
  660.  
  661.     
  662.     def request(self, method, url, body = None, headers = { }):
  663.         
  664.         try:
  665.             self._send_request(method, url, body, headers)
  666.         except socket.error:
  667.             v = None
  668.             if v[0] != 32 or not (self.auto_open):
  669.                 raise 
  670.             
  671.             self._send_request(method, url, body, headers)
  672.  
  673.  
  674.     
  675.     def _send_request(self, method, url, body, headers):
  676.         header_names = []([ k.lower() for k in headers ])
  677.         skips = { }
  678.         if 'accept-encoding' in header_names:
  679.             skips['skip_accept_encoding'] = 1
  680.         
  681.         self.putrequest(method, url, **skips)
  682.         if body and 'content-length' not in header_names:
  683.             self.putheader('Content-Length', str(len(body)))
  684.         
  685.         for hdr, value in headers.iteritems():
  686.             self.putheader(hdr, value)
  687.         
  688.         self.endheaders()
  689.         if body:
  690.             self.send(body)
  691.         
  692.  
  693.     
  694.     def getresponse(self):
  695.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  696.             self._HTTPConnection__response = None
  697.         
  698.         if self._HTTPConnection__state != _CS_REQ_SENT or self._HTTPConnection__response:
  699.             raise ResponseNotReady()
  700.         
  701.         if self.debuglevel > 0:
  702.             response = self.response_class(self.sock, self.debuglevel, strict = self.strict, method = self._method)
  703.         else:
  704.             response = self.response_class(self.sock, strict = self.strict, method = self._method)
  705.         response.begin()
  706.         self._HTTPConnection__state = _CS_IDLE
  707.         if response.will_close:
  708.             self.close()
  709.         else:
  710.             self._HTTPConnection__response = response
  711.         return response
  712.  
  713.  
  714.  
  715. class SharedSocket:
  716.     
  717.     def __init__(self, sock):
  718.         self.sock = sock
  719.         self._refcnt = 0
  720.  
  721.     
  722.     def incref(self):
  723.         self._refcnt += 1
  724.  
  725.     
  726.     def decref(self):
  727.         self._refcnt -= 1
  728.         if self._refcnt == 0:
  729.             self.sock.close()
  730.         
  731.  
  732.     
  733.     def __del__(self):
  734.         self.sock.close()
  735.  
  736.  
  737.  
  738. class SharedSocketClient:
  739.     
  740.     def __init__(self, shared):
  741.         self._closed = 0
  742.         self._shared = shared
  743.         self._shared.incref()
  744.         self._sock = shared.sock
  745.  
  746.     
  747.     def close(self):
  748.         if not self._closed:
  749.             self._shared.decref()
  750.             self._closed = 1
  751.             self._shared = None
  752.         
  753.  
  754.  
  755.  
  756. class SSLFile(SharedSocketClient):
  757.     BUFSIZE = 8192
  758.     
  759.     def __init__(self, sock, ssl, bufsize = None):
  760.         SharedSocketClient.__init__(self, sock)
  761.         self._ssl = ssl
  762.         self._buf = ''
  763.         if not bufsize:
  764.             pass
  765.         self._bufsize = self.__class__.BUFSIZE
  766.  
  767.     
  768.     def _read(self):
  769.         buf = ''
  770.         while True:
  771.             
  772.             try:
  773.                 buf = self._ssl.read(self._bufsize)
  774.             except socket.sslerror:
  775.                 err = None
  776.                 if err[0] == socket.SSL_ERROR_WANT_READ or err[0] == socket.SSL_ERROR_WANT_WRITE:
  777.                     continue
  778.                 
  779.                 if err[0] == socket.SSL_ERROR_ZERO_RETURN or err[0] == socket.SSL_ERROR_EOF:
  780.                     break
  781.                 
  782.                 raise 
  783.                 continue
  784.                 except socket.error:
  785.                     err = None
  786.                     if err[0] == errno.EINTR:
  787.                         continue
  788.                     
  789.                     if err[0] == errno.EBADF:
  790.                         break
  791.                     
  792.                     raise 
  793.                     continue
  794.                 else:
  795.                     break
  796.                 None<EXCEPTION MATCH>socket.error
  797.             return buf
  798.  
  799.  
  800.     
  801.     def read(self, size = None):
  802.         L = [
  803.             self._buf]
  804.         avail = len(self._buf)
  805.         while size is None or avail < size:
  806.             s = self._read()
  807.             if s == '':
  808.                 break
  809.             
  810.             L.append(s)
  811.             avail += len(s)
  812.         all = ''.join(L)
  813.         if size is None:
  814.             self._buf = ''
  815.             return all
  816.         else:
  817.             self._buf = all[size:]
  818.             return all[:size]
  819.  
  820.     
  821.     def readline(self):
  822.         L = [
  823.             self._buf]
  824.         self._buf = ''
  825.         while None:
  826.             i = L[-1].find('\n')
  827.             if i >= 0:
  828.                 break
  829.             
  830.             s = self._read()
  831.             if s == '':
  832.                 break
  833.             
  834.             continue
  835.             if i == -1:
  836.                 return ''.join(L)
  837.             else:
  838.                 all = ''.join(L)
  839.                 i = all.find('\n') + 1
  840.                 line = all[:i]
  841.                 self._buf = all[i:]
  842.                 return line
  843.  
  844.     
  845.     def readlines(self, sizehint = 0):
  846.         total = 0
  847.         list = []
  848.         while True:
  849.             line = self.readline()
  850.             if not line:
  851.                 break
  852.             
  853.             list.append(line)
  854.             total += len(line)
  855.             if sizehint and total >= sizehint:
  856.                 break
  857.                 continue
  858.         return list
  859.  
  860.     
  861.     def fileno(self):
  862.         return self._sock.fileno()
  863.  
  864.     
  865.     def __iter__(self):
  866.         return self
  867.  
  868.     
  869.     def next(self):
  870.         line = self.readline()
  871.         if not line:
  872.             raise StopIteration
  873.         
  874.         return line
  875.  
  876.  
  877.  
  878. class FakeSocket(SharedSocketClient):
  879.     
  880.     class _closedsocket:
  881.         
  882.         def __getattr__(self, name):
  883.             raise error(9, 'Bad file descriptor')
  884.  
  885.  
  886.     
  887.     def __init__(self, sock, ssl):
  888.         sock = SharedSocket(sock)
  889.         SharedSocketClient.__init__(self, sock)
  890.         self._ssl = ssl
  891.  
  892.     
  893.     def close(self):
  894.         SharedSocketClient.close(self)
  895.         self._sock = self.__class__._closedsocket()
  896.  
  897.     
  898.     def makefile(self, mode, bufsize = None):
  899.         if mode != 'r' and mode != 'rb':
  900.             raise UnimplementedFileMode()
  901.         
  902.         return SSLFile(self._shared, self._ssl, bufsize)
  903.  
  904.     
  905.     def send(self, stuff, flags = 0):
  906.         return self._ssl.write(stuff)
  907.  
  908.     sendall = send
  909.     
  910.     def recv(self, len = 1024, flags = 0):
  911.         return self._ssl.read(len)
  912.  
  913.     
  914.     def __getattr__(self, attr):
  915.         return getattr(self._sock, attr)
  916.  
  917.  
  918.  
  919. class HTTPSConnection(HTTPConnection):
  920.     default_port = HTTPS_PORT
  921.     
  922.     def __init__(self, host, port = None, key_file = None, cert_file = None, strict = None):
  923.         HTTPConnection.__init__(self, host, port, strict)
  924.         self.key_file = key_file
  925.         self.cert_file = cert_file
  926.  
  927.     
  928.     def connect(self):
  929.         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  930.         sock.connect((self.host, self.port))
  931.         ssl = socket.ssl(sock, self.key_file, self.cert_file)
  932.         self.sock = FakeSocket(sock, ssl)
  933.  
  934.  
  935.  
  936. class HTTP:
  937.     _http_vsn = 10
  938.     _http_vsn_str = 'HTTP/1.0'
  939.     debuglevel = 0
  940.     _connection_class = HTTPConnection
  941.     
  942.     def __init__(self, host = '', port = None, strict = None):
  943.         if port == 0:
  944.             port = None
  945.         
  946.         self._setup(self._connection_class(host, port, strict))
  947.  
  948.     
  949.     def _setup(self, conn):
  950.         self._conn = conn
  951.         self.send = conn.send
  952.         self.putrequest = conn.putrequest
  953.         self.endheaders = conn.endheaders
  954.         self.set_debuglevel = conn.set_debuglevel
  955.         conn._http_vsn = self._http_vsn
  956.         conn._http_vsn_str = self._http_vsn_str
  957.         self.file = None
  958.  
  959.     
  960.     def connect(self, host = None, port = None):
  961.         if host is not None:
  962.             self._conn._set_hostport(host, port)
  963.         
  964.         self._conn.connect()
  965.  
  966.     
  967.     def getfile(self):
  968.         return self.file
  969.  
  970.     
  971.     def putheader(self, header, *values):
  972.         self._conn.putheader(header, '\r\n\t'.join(values))
  973.  
  974.     
  975.     def getreply(self):
  976.         
  977.         try:
  978.             response = self._conn.getresponse()
  979.         except BadStatusLine:
  980.             e = None
  981.             self.file = self._conn.sock.makefile('rb', 0)
  982.             self.close()
  983.             self.headers = None
  984.             return (-1, e.line, None)
  985.  
  986.         self.headers = response.msg
  987.         self.file = response.fp
  988.         return (response.status, response.reason, response.msg)
  989.  
  990.     
  991.     def close(self):
  992.         self._conn.close()
  993.         self.file = None
  994.  
  995.  
  996. if hasattr(socket, 'ssl'):
  997.     
  998.     class HTTPS(HTTP):
  999.         _connection_class = HTTPSConnection
  1000.         
  1001.         def __init__(self, host = '', port = None, key_file = None, cert_file = None, strict = None):
  1002.             if port == 0:
  1003.                 port = None
  1004.             
  1005.             self._setup(self._connection_class(host, port, key_file, cert_file, strict))
  1006.             self.key_file = key_file
  1007.             self.cert_file = cert_file
  1008.  
  1009.  
  1010.  
  1011.  
  1012. class HTTPException(Exception):
  1013.     pass
  1014.  
  1015.  
  1016. class NotConnected(HTTPException):
  1017.     pass
  1018.  
  1019.  
  1020. class InvalidURL(HTTPException):
  1021.     pass
  1022.  
  1023.  
  1024. class UnknownProtocol(HTTPException):
  1025.     
  1026.     def __init__(self, version):
  1027.         self.args = (version,)
  1028.         self.version = version
  1029.  
  1030.  
  1031.  
  1032. class UnknownTransferEncoding(HTTPException):
  1033.     pass
  1034.  
  1035.  
  1036. class UnimplementedFileMode(HTTPException):
  1037.     pass
  1038.  
  1039.  
  1040. class IncompleteRead(HTTPException):
  1041.     
  1042.     def __init__(self, partial):
  1043.         self.args = (partial,)
  1044.         self.partial = partial
  1045.  
  1046.  
  1047.  
  1048. class ImproperConnectionState(HTTPException):
  1049.     pass
  1050.  
  1051.  
  1052. class CannotSendRequest(ImproperConnectionState):
  1053.     pass
  1054.  
  1055.  
  1056. class CannotSendHeader(ImproperConnectionState):
  1057.     pass
  1058.  
  1059.  
  1060. class ResponseNotReady(ImproperConnectionState):
  1061.     pass
  1062.  
  1063.  
  1064. class BadStatusLine(HTTPException):
  1065.     
  1066.     def __init__(self, line):
  1067.         self.args = (line,)
  1068.         self.line = line
  1069.  
  1070.  
  1071. error = HTTPException
  1072.  
  1073. class LineAndFileWrapper:
  1074.     
  1075.     def __init__(self, line, file):
  1076.         self._line = line
  1077.         self._file = file
  1078.         self._line_consumed = 0
  1079.         self._line_offset = 0
  1080.         self._line_left = len(line)
  1081.  
  1082.     
  1083.     def __getattr__(self, attr):
  1084.         return getattr(self._file, attr)
  1085.  
  1086.     
  1087.     def _done(self):
  1088.         self._line_consumed = 1
  1089.         self.read = self._file.read
  1090.         self.readline = self._file.readline
  1091.         self.readlines = self._file.readlines
  1092.  
  1093.     
  1094.     def read(self, amt = None):
  1095.         if self._line_consumed:
  1096.             return self._file.read(amt)
  1097.         
  1098.         if amt is None or amt > self._line_left:
  1099.             s = self._line[self._line_offset:]
  1100.             self._done()
  1101.             if amt is None:
  1102.                 return s + self._file.read()
  1103.             else:
  1104.                 return s + self._file.read(amt - len(s))
  1105.         else:
  1106.             i = self._line_offset
  1107.             j = i + amt
  1108.             s = self._line[i:j]
  1109.             self._line_offset = j
  1110.             self._line_left -= amt
  1111.             if self._line_left == 0:
  1112.                 self._done()
  1113.             
  1114.             return s
  1115.  
  1116.     
  1117.     def readline(self):
  1118.         if self._line_consumed:
  1119.             return self._file.readline()
  1120.         
  1121.         s = self._line[self._line_offset:]
  1122.         self._done()
  1123.         return s
  1124.  
  1125.     
  1126.     def readlines(self, size = None):
  1127.         if self._line_consumed:
  1128.             return self._file.readlines(size)
  1129.         
  1130.         L = [
  1131.             self._line[self._line_offset:]]
  1132.         self._done()
  1133.         if size is None:
  1134.             return L + self._file.readlines()
  1135.         else:
  1136.             return L + self._file.readlines(size)
  1137.  
  1138.  
  1139.  
  1140. def test():
  1141.     import sys as sys
  1142.     import getopt as getopt
  1143.     (opts, args) = getopt.getopt(sys.argv[1:], 'd')
  1144.     dl = 0
  1145.     for o, a in opts:
  1146.         if o == '-d':
  1147.             dl = dl + 1
  1148.             continue
  1149.     
  1150.     host = 'www.python.org'
  1151.     selector = '/'
  1152.     if args[0:]:
  1153.         host = args[0]
  1154.     
  1155.     if args[1:]:
  1156.         selector = args[1]
  1157.     
  1158.     h = HTTP()
  1159.     h.set_debuglevel(dl)
  1160.     h.connect(host)
  1161.     h.putrequest('GET', selector)
  1162.     h.endheaders()
  1163.     (status, reason, headers) = h.getreply()
  1164.     print 'status =', status
  1165.     print 'reason =', reason
  1166.     print 'read', len(h.getfile().read())
  1167.     print 
  1168.     if headers:
  1169.         for header in headers.headers:
  1170.             print header.strip()
  1171.         
  1172.     
  1173.     print 
  1174.     
  1175.     class HTTP11(HTTP):
  1176.         _http_vsn = 11
  1177.         _http_vsn_str = 'HTTP/1.1'
  1178.  
  1179.     h = HTTP11('www.python.org')
  1180.     h.putrequest('GET', 'http://www.python.org/~jeremy/')
  1181.     h.endheaders()
  1182.     h.getreply()
  1183.     h.close()
  1184.     if hasattr(socket, 'ssl'):
  1185.         for host, selector in (('sourceforge.net', '/projects/python'),):
  1186.             print 'https://%s%s' % (host, selector)
  1187.             hs = HTTPS()
  1188.             hs.set_debuglevel(dl)
  1189.             hs.connect(host)
  1190.             hs.putrequest('GET', selector)
  1191.             hs.endheaders()
  1192.             (status, reason, headers) = hs.getreply()
  1193.             print 'status =', status
  1194.             print 'reason =', reason
  1195.             print 'read', len(hs.getfile().read())
  1196.             print 
  1197.             if headers:
  1198.                 for header in headers.headers:
  1199.                     print header.strip()
  1200.                 
  1201.             
  1202.             print 
  1203.         
  1204.     
  1205.  
  1206. if __name__ == '__main__':
  1207.     test()
  1208.  
  1209.